// 将示例代码封装在一个函数中
pub fn run_examples() {
  println!("===== Rust 字符串示例 =====\n");

  // 1. String 类型定义和基础使用
  println!("1. String 类型定义和基础使用:");
  example_1();

  // 2. &str 字符串字面量类型及使用
  println!("\n2. &str 字符串字面量类型及使用:");
  example_2();

  // 3. String 和 &str 类型转换
  println!("\n3. String 和 &str 类型转换:");
  example_3();

  // 4. 字符串拼接
  println!("\n4. 字符串拼接:");
  example_4();

  // 5. 字符串切片
  println!("\n5. 字符串切片:");
  example_5();

  // 6. 字符串遍历
  println!("\n6. 字符串遍历:");
  example_6();

  // 7. 其他常用方法
  println!("\n7. 其他常用方法:");
  example_7();
}

// 1. String 类型定义和基础使用
fn example_1() {
  println!("  String 是定义在标准库中的类型，分配在堆上，可以动态的增长。它的底层存储是动态字节数组的方式( Vec<u8> )，但是与字节数组不同，String 是 UTF-8 编码");
  let mut s = String::from("");
  println!("  let mut s = String::from(\"\"); // 定义为可变 String 类型");
  s.push_str("hello, world 你好世界");
  println!("  s.push_str(\"hello, world 你好世界\"); // 追加字符串");
  s.push('!');
  println!("  s.push('!'); // 追加字符");
  println!("  s.len(); // 字符串长度: {} 字节", s.len());
  println!("  s.chars.count(); // 字符数量: {}", s.chars().count());
  assert_eq!(s, "hello, world 你好世界!");
}

// 2. &str 字符串字面量类型及使用
fn example_2() {
  println!("  let hello = \"你好，世界!\"; // 字符串字面量定义");
  let hello = "你好，世界!";
  println!("  字符串内容: {}", hello);
  println!("  hello.len(); // 字符串长度: {} 字节", hello.len());
  println!("  hello.chars().count(); // 字符数量: {}", hello.chars().count());
}

// 3. String 和 &str 类型转换
fn example_3() {
  let str = "hello";
  println!("   str.to_string(); // &str 转化为 String: {}", str.to_string());

  let string = String::from("hello world");
  println!("   &string; // string 转化为 &str: {}", &string);

}

// 4. 字符串拼接
fn example_4() {
  println!("  你只能将 String 跟 &str 类型进行拼接，并且 String 的所有权在此过程中会被 move");
  let s1 = String::from("Hello, ");
  let s2 = String::from("Rust!");

  // 使用 + 运算符 (注意: s1被移动了)
  let s3 = s1.clone() + &s2; 
  println!("  let s3 = s1.clone() + &s2; // 注意: s1 加 clone() 就是为了防止 s1 被转移了所有权");

  println!("  s1:{}; s2:{}; s3:{}", s1, s2, s3);
}

// 5. 字符串切片
fn example_5() {
  let text = String::from("Rust编程语言");

  // 注意: 这里必须小心，因为中文字符在UTF-8中占多个字节
  // 下面的切片按照字节进行，可能会导致乱码，这里只取英文部分
  let rust = &text[0..4];
  println!("   let rust = &text[0..4]; // 前4个字节 (Rust): {}", rust);
  println!("   utf8_slice::slice(s, 4, 5); // 后续的中文 utf8 占多个字节, 操作容易出错, 请使用三方库 utf8_slice 来操作");
}

// 6. 遍历字符串
fn example_6() {
  let text = String::from("Rust programmer");
  println!("  遍历字符串:");
  for c in text.chars() {
    print!("   {} ", c);
  }
  print!("\n  按字节遍历:\n  ");
  for b in text.bytes() {
    print!("{} ", b);
  }
  println!("  for in 遍历")
}

// 7. 其他常用方法
fn example_7() {
  let example = String::from("  Hello Rust!  ");
  println!("   原始字符串: \"{}\"", example);
  println!("   example.trim(); // 去除空白: \"{}\"", example.trim());
  println!("   example.to_uppercase(); // 全部大写: \"{}\"", example.to_uppercase());
  println!("   example.to_lowercase(); // 全部小写: \"{}\"", example.to_lowercase());
  println!("   example.contains(\"Rust\") // 包含 \"Rust\": {}", example.contains("Rust"));
  println!("   example.replace(\"Rust\", \"Rust语言\") // 替换: \"{}\"", example.replace("Rust", "Rust语言"));
}